home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 21 / AACD 21.iso / AACD / Utilities / Ghostscript / src / gximage2.c < prev    next >
Encoding:
C/C++ Source or Header  |  2001-01-01  |  10.0 KB  |  318 lines

  1. /* Copyright (C) 1997, 1998, 1999 Aladdin Enterprises.  All rights reserved.
  2.   
  3.   This file is part of AFPL Ghostscript.
  4.   
  5.   AFPL Ghostscript is distributed with NO WARRANTY OF ANY KIND.  No author or
  6.   distributor accepts any responsibility for the consequences of using it, or
  7.   for whether it serves any particular purpose or works at all, unless he or
  8.   she says so in writing.  Refer to the Aladdin Free Public License (the
  9.   "License") for full details.
  10.   
  11.   Every copy of AFPL Ghostscript must include a copy of the License, normally
  12.   in a plain ASCII text file named PUBLIC.  The License grants you the right
  13.   to copy, modify and redistribute AFPL Ghostscript, but only under certain
  14.   conditions described in the License.  Among other things, the License
  15.   requires that the copyright notice and this notice be preserved on all
  16.   copies.
  17. */
  18.  
  19. /*$Id: gximage2.c,v 1.2 2000/09/19 19:00:38 lpd Exp $ */
  20. /* ImageType 2 image implementation */
  21. #include "math_.h"
  22. #include "memory_.h"
  23. #include "gx.h"
  24. #include "gserrors.h"
  25. #include "gsmatrix.h"        /* for gscoord.h */
  26. #include "gscoord.h"
  27. #include "gscspace.h"
  28. #include "gscpixel.h"
  29. #include "gsdevice.h"
  30. #include "gsiparm2.h"
  31. #include "gxgetbit.h"
  32. #include "gxiparam.h"
  33. #include "gxpath.h"
  34.  
  35. /* Forward references */
  36. private dev_proc_begin_typed_image(gx_begin_image2);
  37. private image_proc_source_size(gx_image2_source_size);
  38.  
  39. /* Structure descriptor */
  40. private_st_gs_image2();
  41.  
  42. /* Define the image type for ImageType 2 images. */
  43. const gx_image_type_t gs_image_type_2 = {
  44.     &st_gs_image2, gx_begin_image2, gx_image2_source_size,
  45.     gx_image_no_sput, gx_image_no_sget, gx_image_default_release, 2
  46. };
  47.  
  48. /* Initialize an ImageType 2 image. */
  49. void
  50. gs_image2_t_init(gs_image2_t * pim)
  51. {
  52.     pim->type = &gs_image_type_2;
  53.     pim->UnpaintedPath = 0;
  54.     pim->PixelCopy = false;
  55. }
  56.  
  57. /*
  58.  * Compute the device space coordinates and source data size for an
  59.  * ImageType 2 image.  This procedure fills in
  60.  * image.{Width,Height,ImageMatrix}.
  61.  */
  62. typedef struct image2_data_s {
  63.     gs_point origin;
  64.     gs_int_rect bbox;
  65.     gs_image1_t image;
  66. } image2_data_t;
  67. private int
  68. image2_set_data(const gs_image2_t * pim, image2_data_t * pid)
  69. {
  70.     gs_state *pgs = pim->DataSource;
  71.     gs_matrix smat;
  72.     gs_rect sbox, dbox;
  73.  
  74.     gs_transform(pgs, pim->XOrigin, pim->YOrigin, &pid->origin);
  75.     sbox.q.x = (sbox.p.x = pim->XOrigin) + pim->Width;
  76.     sbox.q.y = (sbox.p.y = pim->YOrigin) + pim->Height;
  77.     gs_currentmatrix(pgs, &smat);
  78.     gs_bbox_transform(&sbox, &smat, &dbox);
  79.     pid->bbox.p.x = (int)floor(dbox.p.x);
  80.     pid->bbox.p.y = (int)floor(dbox.p.y);
  81.     pid->bbox.q.x = (int)ceil(dbox.q.x);
  82.     pid->bbox.q.y = (int)ceil(dbox.q.y);
  83.     pid->image.Width = pid->bbox.q.x - pid->bbox.p.x;
  84.     pid->image.Height = pid->bbox.q.y - pid->bbox.p.y;
  85.     pid->image.ImageMatrix = pim->ImageMatrix;
  86.     return 0;
  87. }
  88.  
  89. /* Compute the source size of an ImageType 2 image. */
  90. private int
  91. gx_image2_source_size(const gs_imager_state * pis, const gs_image_common_t * pim,
  92.               gs_int_point * psize)
  93. {
  94.     image2_data_t idata;
  95.  
  96.     image2_set_data((const gs_image2_t *)pim, &idata);
  97.     psize->x = idata.image.Width;
  98.     psize->y = idata.image.Height;
  99.     return 0;
  100. }
  101.  
  102. /* Begin an ImageType 2 image. */
  103. /* Note that since ImageType 2 images don't have any source data, */
  104. /* this procedure does all the work. */
  105. private int
  106. gx_begin_image2(gx_device * dev,
  107.         const gs_imager_state * pis, const gs_matrix * pmat,
  108.         const gs_image_common_t * pic, const gs_int_rect * prect,
  109.           const gx_drawing_color * pdcolor, const gx_clip_path * pcpath,
  110.         gs_memory_t * mem, gx_image_enum_common_t ** pinfo)
  111. {
  112.     const gs_image2_t *pim = (const gs_image2_t *)pic;
  113.     gs_state *pgs = pim->DataSource;
  114.     gx_device *sdev = gs_currentdevice(pgs);
  115.     int depth = sdev->color_info.depth;
  116.  
  117. /****** ONLY HANDLE depth <= 8 FOR PixelCopy ******/
  118.     bool pixel_copy = pim->PixelCopy && depth <= 8 &&
  119.     !memcmp(&dev->color_info, &sdev->color_info,
  120.         sizeof(dev->color_info));
  121.     bool has_alpha;
  122.     bool direct_copy;
  123.     image2_data_t idata;
  124.     byte *row;
  125.     uint row_size, source_size;
  126.     gx_image_enum_common_t *info;
  127.     gs_matrix smat, dmat;
  128.     gs_color_space cs;
  129.     const gs_color_space *pcs;
  130.     int code;
  131.  
  132.     gs_image_t_init_rgb(&idata.image, pis);
  133.     /* Add Decode entries for K and alpha */
  134.     idata.image.Decode[6] = idata.image.Decode[8] = 0.0;
  135.     idata.image.Decode[7] = idata.image.Decode[9] = 1.0;
  136.     if (pmat == 0) {
  137.     gs_currentmatrix((const gs_state *)pis, &dmat);
  138.     pmat = &dmat;
  139.     } else
  140.     dmat = *pmat;
  141.     gs_currentmatrix(pgs, &smat);
  142.     code = image2_set_data(pim, &idata);
  143.     if (code < 0)
  144.     return code;
  145. /****** ONLY HANDLE SIMPLE CASES FOR NOW ******/
  146.     if (idata.bbox.p.x != floor(idata.origin.x))
  147.     return_error(gs_error_rangecheck);
  148.     if (!(idata.bbox.p.y == floor(idata.origin.y) ||
  149.       idata.bbox.q.y == ceil(idata.origin.y))
  150.     )
  151.     return_error(gs_error_rangecheck);
  152.     source_size = (idata.image.Width * depth + 7) >> 3;
  153.     row_size = max(3 * idata.image.Width, source_size);
  154.     row = gs_alloc_bytes(mem, row_size, "gx_begin_image2");
  155.     if (row == 0)
  156.     return_error(gs_error_VMerror);
  157.     if (pixel_copy &&
  158.     (pcpath == NULL ||
  159.      gx_cpath_includes_rectangle(pcpath,
  160.                      int2fixed(idata.bbox.p.x),
  161.                      int2fixed(idata.bbox.p.y),
  162.                      int2fixed(idata.bbox.q.x),
  163.                      int2fixed(idata.bbox.q.y)))
  164.     ) {
  165.     gs_matrix mat;
  166.  
  167.     idata.image.BitsPerComponent = depth;
  168.     gs_cspace_init_DevicePixel(&cs, depth);
  169.     pcs = &cs;
  170.     /*
  171.      * Figure 7.2 of the Adobe 3010 Supplement says that we should
  172.      * compute CTM x ImageMatrix here, but I'm almost certain it
  173.      * should be the other way around.  Also see gdevx.c.
  174.      */
  175.     gs_matrix_multiply(&idata.image.ImageMatrix, &smat, &mat);
  176.     direct_copy =
  177.         (is_xxyy(&dmat) || is_xyyx(&dmat)) &&
  178. #define eqe(e) mat.e == dmat.e
  179.         eqe(xx) && eqe(xy) && eqe(yx) && eqe(yy);
  180. #undef eqe
  181.     has_alpha = false;    /* no separate alpha channel */
  182.     } else {
  183.     pixel_copy = false;
  184.     idata.image.BitsPerComponent = 8;
  185.     /* Always use RGB source color for now. */
  186.     pcs = gs_cspace_DeviceRGB(pis);
  187.     direct_copy = false;
  188.     /*
  189.      * The source device has alpha if the same RGB values with
  190.      * different alphas map to different pixel values.
  191.      ****** THIS IS NOT GOOD ENOUGH: WE WANT TO SKIP TRANSFERRING
  192.      ****** ALPHA IF THE SOURCE IS CAPABLE OF HAVING ALPHA BUT
  193.      ****** DOESN'T CURRENTLY HAVE ANY ACTUAL ALPHA VALUES DIFFERENT
  194.      ****** FROM 1.
  195.      */
  196.     /*
  197.      * Since the default implementation of map_rgb_alpha_color
  198.      * premultiplies the color towards white, we can't just test
  199.      * whether changing alpha has an effect on the color.
  200.      */
  201.     {
  202.         gx_color_index trans_black =
  203.         (*dev_proc(sdev, map_rgb_alpha_color))
  204.         (sdev, (gx_color_value) 0, (gx_color_value) 0,
  205.          (gx_color_value) 0, (gx_color_value) 0);
  206.  
  207.         has_alpha =
  208.         trans_black != (*dev_proc(sdev, map_rgb_alpha_color))
  209.         (sdev, (gx_color_value) 0, (gx_color_value) 0,
  210.          (gx_color_value) 0, gx_max_color_value) &&
  211.         trans_black != (*dev_proc(sdev, map_rgb_alpha_color))
  212.         (sdev, gx_max_color_value, gx_max_color_value,
  213.          gx_max_color_value, gx_max_color_value);
  214.     }
  215.     }
  216.     idata.image.ColorSpace = pcs;
  217.     idata.image.Alpha =
  218.     (has_alpha ? gs_image_alpha_last : gs_image_alpha_none);
  219.     if (smat.yy < 0) {
  220.     /*
  221.      * The source Y axis is reflected.  Reflect the mapping from
  222.      * user space to source data.
  223.      */
  224.     idata.image.ImageMatrix.ty += idata.image.Height *
  225.         idata.image.ImageMatrix.yy;
  226.     idata.image.ImageMatrix.xy = -idata.image.ImageMatrix.xy;
  227.     idata.image.ImageMatrix.yy = -idata.image.ImageMatrix.yy;
  228.     }
  229.     if (!direct_copy)
  230.     code = (*dev_proc(dev, begin_typed_image))
  231.         (dev, pis, pmat, (const gs_image_common_t *)&idata.image, NULL,
  232.          pdcolor, pcpath, mem, &info);
  233.     if (code >= 0) {
  234.     int y;
  235.     gs_int_rect rect;
  236.     gs_get_bits_params_t params;
  237.     const byte *data;
  238.     uint offset = row_size - source_size;
  239.  
  240.     rect = idata.bbox;
  241.     for (y = 0; code >= 0 && y < idata.image.Height; ++y) {
  242.         gs_int_rect *unread = 0;
  243.         int num_unread;
  244.  
  245. /****** y COMPUTATION IS ROUNDED -- WRONG ******/
  246.         rect.q.y = rect.p.y + 1;
  247.         /* Insist on x_offset = 0 to simplify the conversion loop. */
  248.         params.options =
  249.         GB_ALIGN_ANY | (GB_RETURN_COPY | GB_RETURN_POINTER) |
  250.         GB_OFFSET_0 | (GB_RASTER_STANDARD | GB_RASTER_ANY) |
  251.         GB_PACKING_CHUNKY;
  252.         if (pixel_copy) {
  253.         params.options |= GB_COLORS_NATIVE;
  254.         params.data[0] = row + offset;
  255.         code = (*dev_proc(sdev, get_bits_rectangle))
  256.             (sdev, &rect, ¶ms, &unread);
  257.         if (code < 0)
  258.             break;
  259.         num_unread = code;
  260.         data = params.data[0];
  261.         if (direct_copy) {
  262.             /*
  263.              * Copy the pixels directly to the destination.
  264.              * We know that the transformation is only a translation,
  265.              * but we must handle an inverted destination Y axis.
  266.              */
  267.             code = (*dev_proc(dev, copy_color))
  268.             (dev, data, 0, row_size, gx_no_bitmap_id,
  269.              (int)(dmat.tx - idata.image.ImageMatrix.tx),
  270.              (int)(dmat.ty - idata.image.ImageMatrix.ty +
  271.                    (dmat.yy < 0 ? ~y : y)),
  272.              idata.image.Width, 1);
  273.             continue;
  274.         }
  275.         } else {
  276.         /*
  277.          * Convert the pixels to pure colors.  This may be very
  278.          * slow and painful.  Eventually we will use indexed color for
  279.          * narrow pixels.
  280.          */
  281.         /* Always use RGB source color for now. */
  282.         params.options |=
  283.             GB_COLORS_RGB | GB_DEPTH_8 |
  284.             (has_alpha ? GB_ALPHA_LAST : GB_ALPHA_NONE);
  285.         params.data[0] = row;
  286.         code = (*dev_proc(sdev, get_bits_rectangle))
  287.             (sdev, &rect, ¶ms, &unread);
  288.         if (code < 0)
  289.             break;
  290.         num_unread = code;
  291.         data = params.data[0];
  292.         }
  293.         if (num_unread > 0 && pim->UnpaintedPath) {
  294.         /* Add the rectangle(s) to the unpainted path. */
  295.         int i;
  296.  
  297.         for (i = 0; code >= 0 && i < num_unread; ++i)
  298.             code = gx_path_add_rectangle(pim->UnpaintedPath,
  299.                          int2fixed(unread[i].p.x),
  300.                          int2fixed(unread[i].p.y),
  301.                          int2fixed(unread[i].q.x),
  302.                          int2fixed(unread[i].q.y));
  303.         gs_free_object(dev->memory, unread, "UnpaintedPath unread");
  304.         }
  305.         code = gx_image_data(info, &data, 0, row_size, 1);
  306.         rect.p.y = rect.q.y;
  307.     }
  308.     if (!direct_copy) {
  309.         if (code >= 0)
  310.         code = gx_image_end(info, true);
  311.         else
  312.         discard(gx_image_end(info, false));
  313.     }
  314.     }
  315.     gs_free_object(mem, row, "gx_begin_image2");
  316.     return (code < 0 ? code : 1);
  317. }
  318.